import 'package:flutter_menu/model/login_model.dart';
import 'package:flutter_menu/model/menu_model.dart';
import 'package:flutter_menu/objectbox.g.dart';
import 'package:objectbox_flutter_libs/objectbox_flutter_libs.dart';

import '../model/category_model.dart';
import '../model/formula_model.dart';
import '../model/material_model.dart';
import '../model/product_model.dart';
import '../model/sellout_model.dart';
import '../model/shope_model.dart';

late Store store;

Future<Store> initStore() async {
  store = await openStore();
  // if (kDebugMode) store.admin();
  return store;
}

void deleteDB() async {
  var path = (await defaultStoreDirectory()).path;
  Store.removeDbFiles(path);
}
List<_TableInfo> _tableInfo = [
  _TableInfo(store.box<SupplyTime>,SupplyTime_.updateTime),
  _TableInfo(store.box<FormulaModel>,FormulaModel_.updateTime),
  _TableInfo(store.box<FormulaListFormulaMaterial>,FormulaListFormulaMaterial_.updateTime),
  _TableInfo(store.box<UserModel>,UserModel_.updateTime),
  _TableInfo(store.box<MaterialModel>,MaterialModel_.updateTime),
  _TableInfo(store.box<MaterialDeptStockModel>,MaterialDeptStockModel_.updateTime),
  _TableInfo(store.box<OptionMaterialModel>,OptionMaterialModel_.updateTime),
  _TableInfo(store.box<OptionMaterialListFormulaMaterial>,OptionMaterialListFormulaMaterial_.updateTime),
  _TableInfo(store.box<CustomMenuModel>,CustomMenuModel_.updateTime),
  _TableInfo(store.box<CustomMenuListCategoryList>,CustomMenuListCategoryList_.updateTime),
  _TableInfo(store.box<CategoryListProductList>,CategoryListProductList_.updateTime),
  _TableInfo(store.box<ElectronicMenuModel>,ElectronicMenuModel_.updateTime),
  _TableInfo(store.box<ElectronicMenuProduct>,ElectronicMenuProduct_.updateTime),
  _TableInfo(store.box<DishList>,DishList_.updateTime),
  _TableInfo(store.box<ProductModel>,ProductModel_.updateTime),
  _TableInfo(store.box<Group>,Group_.updateTime),
  _TableInfo(store.box<Food>,Food_.updateTime),
  _TableInfo(store.box<Spec>,Spec_.updateTime),
  _TableInfo(store.box<SpecOption>,SpecOption_.updateTime),
  _TableInfo(store.box<ProductListSupplyTime>,ProductListSupplyTime_.updateTime),
  _TableInfo(store.box<ShopModel>,ShopModel_.updateTime),
  _TableInfo(store.box<ShopTableInfoModel>,ShopTableInfoModel_.updateTime),
  _TableInfo(store.box<TableModel>,TableModel_.updateTime),
  _TableInfo(store.box<DeptModel>,DeptModel_.updateTime),
  _TableInfo(store.box<MarketTypeModel>,MarketTypeModel_.updateTime),
  _TableInfo(store.box<SelloutModel>,SelloutModel_.updateTime),
];

extension StoreExt on Store {
  Admin? admin() {
    Admin? admin;
    if (Admin.isAvailable()) {
      admin = Admin(this);
    }
    return admin;
  }

  void removeAll({int? time }) {
    for (var info in _tableInfo) {
      Box box = info.boxFc.call();
      if(time !=null){
        box.removeByTimeStamp(info.timeProperty, time);
      }else{
        box.removeAll();
      }
    }
  }

  UserModel? login(String account, String pwd) {
    var _box = store.box<UserModel>();
    var query =
        _box.query(UserModel_.nickName.equals(account) & UserModel_.password.equals(pwd)).build();
    return query.findUnique();
  }


}

extension BoxExt<T> on Box<T> {
  int removeByTimeStamp(QueryIntegerProperty<T> timeProperty, int timeStamp) {
    var ids = query(timeProperty.lessThan(timeStamp).or(timeProperty.isNull())).build().findIds();
    return removeMany(ids);
  }
}

extension BoxExt2<T extends IEntity > on Box<T> {

  int update(T t,QueryStringProperty<T> idProperty,String? id){
    var result ;
    if(id !=null) {
      result = query(idProperty.equals(id??"")).build().findFirst();
      if (result != null) {
        t.obxId = result.obxId;
      }
    }
    int objId =  put(t);
    t.obxId = objId;
    return objId;
  }
}

extension ToManyExt<T> on ToMany<T> {
  void refresh() {}
}

mixin IEntity {
  int update(Store store,int? time);
  int get obxId;
  set obxId(int id) ;
  int get updateTime;
  set updateTime(int updateTime);

}

class _TableInfo{
  Function boxFc;
  QueryIntegerProperty timeProperty;

  _TableInfo(this.boxFc, this.timeProperty);


}
